// nxtDlg.cpp : implementation file
//

#include "stdafx.h"
#include "NXTPocketPC.h"
#include "nxtDlg.h"
#include "serial.hpp"
#include "motor.hpp"
#include "brick.hpp"
#include "ButtonRight.h"
#include "ButtonLeft.h"
#include "ButtonFwd.h"
#include "ButtonRev.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE

static char THIS_FILE[] = __FILE__;
#endif

#ifndef REMOTE
#define REMOTE

int dirA=1;
int dirB=1;

Serial bluetooth;

Motor motor1;
Motor motor2; 
Brick nxt=Brick(&bluetooth);


//Buttons 
CButton *con_button  = new CButton; 
CButton *con_group   = new CButton; //Connection Group box 
CButton *motor_group = new CButton; //Motor group box 


//Movement buttons
ButtonRight *right_button   = new ButtonRight;
ButtonLeft *left_button     = new ButtonLeft;
ButtonFwd *fwd       = new ButtonFwd;
ButtonRev *rev       = new ButtonRev;


//Combo box
CComboBox *comport_cb = new CComboBox;
CComboBox *motor1_cb  = new CComboBox;
CComboBox *motor2_cb  = new CComboBox;

//Check box
CButton *motor1_float   = new CButton;
CButton *motor1_reverse = new CButton;
CButton *motor2_float   = new CButton;
CButton *motor2_reverse = new CButton;

//Speed Label
CStatic *speed_label = new CStatic;
CStatic *status_label = new CStatic;


//Slider
CSliderCtrl *speed = new CSliderCtrl;
#endif

/////////////////////////////////////////////////////////////////////////////
// CNxtDlg dialog

CNxtDlg::CNxtDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CNxtDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CNxtDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CNxtDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CNxtDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CNxtDlg, CDialog)
	//{{AFX_MSG_MAP(CNxtDlg)
	ON_BN_CLICKED(IDC_CONNECT, on_connect)
	ON_CBN_SELENDOK(IDC_MOTOR1, on_change_motor1)
	ON_CBN_SELENDOK(IDC_MOTOR2, on_change_motor2)
	ON_BN_CLICKED(IDC_MOTOR1_REVERSE, on_check_reverse_m1)
	ON_BN_CLICKED(IDC_MOTOR2_REVERSE, on_check_reverse_m2)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNxtDlg message handlers

BOOL CNxtDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	CenterWindow(GetDesktopWindow());	// center to the hpc screen

	create_layout();
	return TRUE;  // return TRUE  unless you set the focus to a control
}

//layout creation
void CNxtDlg::create_layout(){
    //Connect button
	con_button = new CButton;
	con_button->Create(_T("Connect"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(20, 20, 100, 40), this, IDC_CONNECT);
	
	
	//connection combo box (comport)
	comport_cb->Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, CRect(110, 20, 160, 120), this, IDC_COMPORT);
    comport_cb->AddString(_T("Com1"));
    comport_cb->AddString(_T("Com2"));
    comport_cb->AddString(_T("Com3"));
    comport_cb->AddString(_T("Com4"));
	comport_cb->AddString(_T("Com5"));
	comport_cb->AddString(_T("Com6"));
	comport_cb->AddString(_T("Com7"));
	comport_cb->AddString(_T("Com8"));
	comport_cb->AddString(_T("Com9"));
	comport_cb->SetCurSel(0);
    
	//Status label
    status_label->Create(_T("Not Connected"), WS_CHILD | WS_VISIBLE, CRect(175, 17, 225, 42), this, IDC_STATUS_LABEL);
	CFont *f = new CFont;
	f->CreatePointFont(70, _T("Garamond"));
    status_label->SetFont(f,true);

	//Connection groupbox
	con_group->Create(_T("Connection"), WS_CHILD | WS_VISIBLE | BS_GROUPBOX, CRect(10, 0, 230, 50 ), this, IDC_CONNECT_GROUP); 

	//Motor 1 combo box 
	motor1_cb->Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, CRect(20, 75, 100, 165), this, IDC_MOTOR1);
    motor1_cb->AddString(_T("Motor A"));
    motor1_cb->AddString(_T("Motor B"));
    motor1_cb->AddString(_T("Motor C"));
    motor1_cb->SetCurSel(0);
    
    //Motor 1 check boxes
    motor1_float->Create(_T("Float"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX ,	CRect(20, 100, 100, 115 ), this, IDC_MOTOR1_FLOAT);
    motor1_reverse->Create(_T("Reverse"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX ,	CRect(20, 120, 100, 135 ), this, IDC_MOTOR1_REVERSE);


	//Motor 2 combo box 
	motor2_cb->Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, CRect(130, 75, 220, 165), this, IDC_MOTOR2);
    motor2_cb->AddString(_T("Motor A"));
    motor2_cb->AddString(_T("Motor B"));
    motor2_cb->AddString(_T("Motor C"));
    motor2_cb->SetCurSel(1);
	
	//Motor 2 check boxes
    motor2_float->Create(_T("Float"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX ,	CRect(130, 100, 210, 115 ), this, IDC_MOTOR2_FLOAT);
    motor2_reverse->Create(_T("Reverse"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX ,	CRect(130, 120, 210, 135 ), this, IDC_MOTOR2_REVERSE);

	
	//Speed label
    speed_label->Create(_T("Set speed"), WS_CHILD | WS_VISIBLE, CRect(20, 140, 80, 160), this, IDC_SPEED_LABEL);
	CFont *font = new CFont;
	font->CreatePointFont(100, _T("Garamond"));
    speed_label->SetFont(font,true);
	
	//Speed slider
	speed->Create(WS_CHILD | WS_VISIBLE, CRect(90, 140, 210, 168), this, IDC_SPEED);
	speed->SetRange(0,10);
	speed->SetTicFreq(1);
	speed->SetPos(7);
	
	//Motor groupbox
	motor_group->Create(_T("Motors"), WS_CHILD | WS_VISIBLE | BS_GROUPBOX, CRect(10, 55, 230, 170 ), this, IDC_MOTOR_GROUP); 
	
	//Movements buttons
    left_button->Create(_T("LEFT"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(10, 175, 60, 255), this, IDC_LEFT);
    left_button->dialog = this;
    
	right_button->Create(_T("RIGHT"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(180, 175, 230, 255), this, IDC_RIGHT);
    right_button->dialog = this;


	fwd->Create(_T("FWD"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(80, 175, 160, 210), this, IDC_FWD);
    fwd->dialog = this;


	rev->Create(_T("REV"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(80, 220, 160, 255), this, IDC_REV);
    rev->dialog = this;

	enable_remote(false);

}


void CNxtDlg::on_connect() 
{
	CString caption;
	con_button->GetWindowText(caption);
	
	CString com_selected;
	int index = comport_cb->GetCurSel();
    comport_cb->GetLBText(index, com_selected);
	com_selected = com_selected +":";
	
	if(caption == "Disconnect"){
        bluetooth.disconnect();
        
		status_label->SetWindowText(_T("Not Connected"));
		comport_cb->EnableWindow(true);
		con_button->SetWindowText(_T("Connect"));
        enable_remote(false);
        
    }
    
	else{
        con_button->EnableWindow(false);
		comport_cb->EnableWindow(false);
		status_label->SetWindowText(_T("Wait"));   
		
		if ( bluetooth.connect(com_selected) ){//Connect to NXT
           
			if(nxt.battery_level()){//Check if there is an answer from NXT
               
			   con_button->SetWindowText(_T("Disconnect"));
			   
			   motor1 = Motor(motor1_cb->GetCurSel(), &bluetooth);
               motor2 = Motor(motor2_cb->GetCurSel(), &bluetooth);
			   
			   enable_remote(true);
               con_button->EnableWindow(true);
		
  		       status_label->SetWindowText(_T("Connected"));
			   return;

           }
           else{
               con_button->EnableWindow(true);
			   comport_cb->EnableWindow(true);
			   bluetooth.disconnect();
               status_label->SetWindowText(_T("No NXT Found"));
			   
           }
        }
        else{
			 comport_cb->EnableWindow(true);
             con_button->EnableWindow(true); 
			 status_label->SetWindowText(_T("Couldn't Open Port"));
        }
    }
}


void CNxtDlg::on_change_motor1() 
{
     motor1 = Motor(motor1_cb->GetCurSel(), &bluetooth);		
}

void CNxtDlg::on_change_motor2() 
{
	motor2 = Motor(motor2_cb->GetCurSel(), &bluetooth);
}

void CNxtDlg::on_check_reverse_m1() 
{
     if(IsDlgButtonChecked(IDC_MOTOR1_REVERSE)){
         dirA=-1;
      }
      else{
         dirA=1;
      }	
}

void CNxtDlg::on_check_reverse_m2() 
{
     if(IsDlgButtonChecked(IDC_MOTOR2_REVERSE)){
         dirB=-1;
      }
      else{
         dirB=1;
      }		
     	
}


void CNxtDlg::turn_left(){
    motor1.on(-speed->GetPos() * 10 * dirA);
    motor2.on(speed->GetPos() * 10 * dirB);
}


void CNxtDlg::turn_right(){
    motor1.on(speed->GetPos() * 10 * dirA);
    motor2.on(-speed->GetPos() * 10 * dirB);
  

}


void CNxtDlg::forward(){
    motor1.on(speed->GetPos() * 10 * dirA);
    motor2.on(speed->GetPos() * 10 * dirB);
	
}


void CNxtDlg::backwards(){
    motor1.on(-speed->GetPos() * 10 * dirA);
    motor2.on(-speed->GetPos() * 10 * dirB);
	
}


void CNxtDlg::stop(){
    
	if(IsDlgButtonChecked(IDC_MOTOR1_FLOAT)){
        motor1.off();
    }
    else{
        motor1.stop();

    }

    if(IsDlgButtonChecked(IDC_MOTOR2_FLOAT)){
        motor2.off();
    }
    else{
        motor2.stop();

    }


}

void CNxtDlg::enable_remote(bool set){
    
	right_button->EnableWindow(set);
	left_button->EnableWindow(set);
    fwd->EnableWindow(set);
	rev->EnableWindow(set);
	
	motor1_cb->EnableWindow(set);
	motor2_cb->EnableWindow(set);
	
	motor1_float->EnableWindow(set);
	motor1_reverse->EnableWindow(set);

	motor2_float->EnableWindow(set);
	motor2_reverse->EnableWindow(set);
	
	speed->EnableWindow(set);
	speed_label->EnableWindow(set);
}

